require_relative 'comb/version'
require 'json'
require 'time'

class Comb
  def self.assemble(path_to_modules)
    new(path_to_modules).assemble
  end

private

  def initialize(path_to_modules)
    # instance vars are just global vars in sheeps clothing
    @path_to_modules = path_to_modules
    @output = [] 
    @timestamp = Time.new.utc.iso8601 # baaaaaaaaaaa
  end

public
  
  def assemble
    mark_start_of_output
    append_require_snippet
    for_each_js_module do |name, code|
      append_module(name, code)
    end
    for_each_html_template do |name, template|
      append_template(name, template)
    end
    mark_end_of_output
    return_output
  end

private

  def mark_start_of_output
    @output << "// generated by comb on #{@timestamp}"
  end

  def append_require_snippet
    @output << (<<-eos
var require = function(module) {
  return require.registry[module]()
}
require.registry = {}
require.register = function(module, code) {
  require.registry[module] = code
}
    eos
    ).chomp
  end

  def for_each_js_module
    for_each_file('js') { |name, code| yield name, code }
  end

  def for_each_html_template
    for_each_file('html') { |name, template| yield name, template }
  end

  def for_each_file(ext)
    Dir.glob(@path_to_modules + "/**/*.#{ext}").each do |path| 
      # get the module 'name' by removing the path and the extension
      name = path.gsub(@path_to_modules, '').gsub(/^\//, '').gsub(/\.js$/, '')
      code = File.open(path) { |f| f.read }
      yield name, code
    end
  end

  def append_module(name, code)
      @output << (<<-eos
require.register('#{name}', function() {
#{indent_code(code)}
})
      eos
      ).chomp
  end

  def append_template(name, template)
      @output << (<<-eos
require.register('#{name}', function() {
  return #{template.gsub("\n", ' ').gsub(/\s+/, ' ' ).strip.to_json}
})
      eos
      ).chomp
  end

  def indent_code(code)
    code.split("\n").collect { |line| "  #{line}" }.join("\n")
  end

  def mark_end_of_output
    @output << "// end of comb output at #{@timestamp}"
  end

  def return_output
    @output.join("\n")
  end
end
